package eu.livotov.jsms.impl;

import eu.livotov.jsms.SMSException;
import eu.livotov.jsms.SMSMessage;
import eu.livotov.jsms.SMSProvider;
import eu.livotov.jsms.util.CryptoTool;
import eu.livotov.jsms.util.XmlTool;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.UUID;

/**
 * Created with IntelliJ IDEA.
 * User: dlivotov
 * Date: 14.04.12
 * Time: 21:53
 * To change this template use File | Settings | File Templates.
 */
public class WEBSMSProvider implements SMSProvider
{

    private String gmUser;
    private String gmPassword;

    private final static SimpleDateFormat timeStampFormatter = new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss Z");
    // Mon, 02 Apr 2007 11:58:24 +0300
    private final static String API_ENDPOINT = "https://websms.ru/xml_in5.asp";

    public WEBSMSProvider(final String login, final String password)
    {
        gmUser = CryptoTool.encryptString(login);
        gmPassword = CryptoTool.encryptString(password);
    }

    public String getName()
    {
        return "WEBSMS.ru provider";
    }

    public SMSMessage sendMessage(SMSMessage sms)
    {
        try
        {
            sms.setId(UUID.randomUUID().toString());

            DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = builderFactory.newDocumentBuilder();
            Document requestDoc = builder.newDocument();

            Element root = requestDoc.createElement("message");
            requestDoc.appendChild(root);

            Element service = requestDoc.createElement("service");
            root.appendChild(service);

            service.setAttribute("id", sms.getNumbers().size() == 1 ? "individual" : "bulk");
            service.setAttribute("login", gmUser);
            service.setAttribute("password", gmPassword);
            service.setAttribute("uniq_key", sms.getId());
            service.setAttribute("source", sms.getSender());

            if (sms.getDeliveryDate() != null && sms.getDeliveryDate().getTime() > System.currentTimeMillis())
            {
                service.setAttribute("start", timeStampFormatter.format(sms.getDeliveryDate()));
            }

            for (String num : sms.getNumbers())
            {
                Element phone = requestDoc.createElement("to");
                phone.setTextContent(num.trim());
                root.appendChild(phone);
            }

            Element body = requestDoc.createElement("body");
            body.setTextContent(sms.getText().trim());
            root.appendChild(body);

            URL url = new URL(API_ENDPOINT);
            HttpURLConnection huc = (HttpURLConnection) url.openConnection();
            huc.setDoOutput(true);
            huc.setDoInput(true);
            huc.setRequestMethod("POST");
            huc.setRequestProperty("Content-Type", "application/xml");
            OutputStream os = huc.getOutputStream();

            os.write(XmlTool.xmlToString(requestDoc).getBytes("utf-8"));
            os.flush();
            os.close();

            InputStream is = huc.getInputStream();
            InputStreamReader inputstreamreader = new InputStreamReader(is);
            BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
            StringBuffer inString = new StringBuffer();
            String s3;

            while ((s3 = bufferedreader.readLine()) != null)
            {
                inString.append(s3).append("\n");
            }

            bufferedreader.close();
            huc.disconnect();

            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);
            Document dom = builder.parse(new ByteArrayInputStream(inString.toString().getBytes()));

            NodeList statusNodes = dom.getElementsByTagName("state");

            if (statusNodes.getLength() > 0)
            {
                Element status = (Element) statusNodes.item(0);
                int statusCode = 1;

                if (status.hasAttribute("errcode"))
                {
                    statusCode = Integer.parseInt(status.getAttribute("errcode"));
                } else
                {
                    final String errMessage = status.getAttribute("error");
                    final String state = status.getTextContent().trim();

                    if (!"Accepted".equalsIgnoreCase(state))
                    {
                        throw new SMSException(-1, errMessage);
                    }
                }

                if (statusCode != 0)
                {
                    throw new SMSException(statusCode, describeErrorCode(statusCode));
                }
            }

        } catch (Throwable err)
        {
            err.printStackTrace();
            throw new SMSException(err);
        }

        return sms;
    }

    private String describeErrorCode(final int statusCode)
    {
        switch (statusCode)
        {
            default:
                return "Undescriped WEBSMS error code: " + statusCode + ", please check the latest API manual.";
        }
    }

}
